/**
 * The prefix for the IDs of the checkboxes in a table
 */
var checkboxIdPrefix = "action_check_";

/**
 * The base for the selector used to get all checkboxes used to execute actions
 */
var baseCheckboxSel = " td input:checkbox[id^='" + checkboxIdPrefix + "']";

/**
 * The ID for the main check box : the one used to select all the current page
 * check boxes.
 */
var mainCheckBoxId = "mainCheckBox";

/**
 * The ID for the component used to store IDs corresponding to a set of selected
 * table rows. Must be a "select" HTML component.
 */
var selCmpId = "selCmpId";

/**
 * The ID for the button used to remove items from the selection component.
 */
var selCmpRmBtId = "selCmpRmBtId";

/**
 * The map associating a table ID to the corresponding actions data
 */
var tableIdToActionsData = new Array();

/**
 * Modifies the state of checkboxes inside a table according to the state of the
 * checkbox denoted by the passed ID.
 *
 * @param tableId
 *            The ID of the table where the checkbox are stored.
 * @return void
 */
function handleTableCheckBoxSel(tableId) {

	var isMainChecked;
	$("#" + mainCheckBoxId).each(function() {
		isMainChecked = this.checked;
	});

	$("#" + tableId + baseCheckboxSel + ":enabled").each(function() {
		this.checked = isMainChecked;
	});

	updateRowsState(tableId);
}

/**
 * Inits the behavior of the checkboxes found in the table denoted by the passed
 * ID. The state of the action buttons denoted by the passed IDs is modified
 * according to the checkbox selection.
 *
 * @param tableId
 *            A table ID
 * @param actionsData
 *            An array of actions data. Each array cell contains data about an
 *            action. For each action, an array of 3 elements must be defined
 *            and contain : the button ID, the maximum number of selected
 *            checkboxes for the action, the error message to display if too
 *            many checkboxes are selected for the action.
 *
 * @return void
 */
function initTableCheckboxesActions(tableId, actionsData) {

	tableIdToActionsData[tableId] = actionsData;

	// updating the table rows state
	$("#" + tableId + " input:checkbox:enabled").each(function() {
		this.checked = false;
	});
	$("#" + tableId + baseCheckboxSel + ":enabled").click(function() {
		updateRowsState(tableId);
	});
}

/**
 * Modifies the rows state of the table denoted by the passed ID.
 *
 * @param tableId
 *            A table ID
 * @return void
 */
function updateRowsState(tableId) {

	/* modifying the row class of each selected checkbox */
	var checkedInputs = $("#" + tableId + baseCheckboxSel + ":enabled:checked");
	var tr = checkedInputs.parents("tr").addClass("selected").next("tr")
			.addClass("after-selected");
	$("#" + tableId + " input:checkbox:enabled").not(checkedInputs)
			.parent("td").parent("tr").removeClass("selected").next("tr")
			.removeClass("after-selected");

	/* modifying each action state according to the selected checkboxes */
	$.each(tableIdToActionsData[tableId], function(index, value) {

		/*
		 * getting the buttons and removing the previously-attached events
		 * handler
		 */
		var enableBtn = false;
		var buttons = $("." + value[0]);

		if (buttons.length > 0) {

			var btContents = buttons.find("span.content");
			btContents.unbind();

			/* checking if the max selected checkboxes nb is reached */
			if (value[1] > 0 && checkedInputs.length > value[1]) {

				var msg = value[2];

				/* adding an event listener to display the error message */
				btContents.hover(function() {
					var el = $(this);
					showInfoBox(el, msg);
				}, function() {
					hideInfoBox();
				});

			} else if (checkedInputs.length > 0) {

				enableBtn = true;
			}

			buttons.each(function(){setFormElementEnabled($(this), enableBtn);});
		}
	});
}

/**
 * Computes the number of selected rows in the table denoted by the passed ID.
 *
 * @param tableId
 *            A table ID
 * @return The number of selected rows in the table
 */
function getSelectedRowsNb(tableId) {

	return $("#" + tableId + baseCheckboxSel + ":enabled:checked").length;
}

/**
 * Displays the page denoted by the passed URL. The URL is added a parameter
 * whose value contains the list of the IDs for which the action should be
 * executed.
 *
 * @param tableId
 *            A table ID
 * @param url
 *            An url
 * @param paramName
 *            The parameter name for the IDs
 * @return void
 */
function execActionForTableRows(tableId, url, paramName) {

	execActionForTableRows(tableId, url, paramName, false, null, null);
}

/**
 * Displays the page denoted by the passed URL. The URL is added a parameter
 * whose value contains the list of the IDs for which the action should be
 * executed.
 *
 * @param tableId
 *            A table ID
 * @param url
 *            An url
 * @param paramName
 *            The parameter name for the IDs
 * @param async
 *            Whether the url should be requested asynchonously
 * @param asyncSuccessFn
 *            The function to execute if the async call succeeds.
 * @param asyncFailureFn
 *            The function to execute if the async call fails. The request data
 *            object is passed to the method.
 * @return void
 */
function execActionForTableRows(tableId, url, paramName, async, asyncSuccessFn,
		asyncFailureFn) {

	/* building the url parameter */
	var theIds = "";
	var selector = "#" + tableId + baseCheckboxSel + ":enabled:checked";

	$(selector).each(
			function() {

				if (theIds != "") {
					theIds += ",";
				}

				/* getting the checkbox id and the element id */
				var checkboxId = $(this).attr("id");
				var theId = checkboxId.substring(checkboxIdPrefix.length,
						checkboxId.length);
				theIds += theId;
			});

	if (url.indexOf('?', 0) == -1) {

		url += "?";

	} else {

		url += "&";
	}

	url += paramName + "=" + theIds;

	if (async) {

		// executing the async request
		$.get(url, function(data) {

			if (data == 'OK') {

				asyncSuccessFn();

			} else {

				asyncFailureFn(data);
			}
		});

	} else {

		document.location = url;
	}
}

/**
 * Inits the behavior of the selection component. The table rows are also
 * modified to represent the current selection state.
 *
 * @param tableId
 *            A table ID
 *
 * @return void
 */
function initSelectionComponents(tableId) {

	// updating the selection component state
	selectLastSelectionComponentOption();
	updateSelectionComponentState();

	// updating the table rows state
	updateRowsStateForSelection(tableId);
}

/**
 * Updates the selection components state according to the current selection.
 *
 * @return void
 */
function updateSelectionComponentState() {

	// disabling the button if the selection is empty
	var selOptions = $('#' + selCmpId + ' option:selected');
	var enableBt = selOptions.length > 0;
	var cmpBt = $('#' + selCmpRmBtId);
	setFormElementEnabled(cmpBt.parent(), enableBt);
	setFormElementEnabled(cmpBt, enableBt);
}

/**
 * Selects the last selection component option.
 *
 * @return void
 */
function selectLastSelectionComponentOption() {

	// selecting the last component option
	$('#' + selCmpId + ' option:selected').each(function() {
		setSelected($(this), false);
	});

	$('#' + selCmpId + ' option:last').each(function() {
		setSelected($(this), true);
	});
}

/**
 * Modifies the rows state of the table denoted by the passed ID for the current
 * selection.
 *
 * @param tableId
 *            A table ID
 * @return void
 */
function updateRowsStateForSelection(tableId) {

	// getting all the selected items
	var selectedItems = new Array();

	$('#' + selCmpId + ' option').each(function() {
		selectedItems.push($(this).text());
	});

	/*
	 * checking if the table row matches a selected item. If so, checks and
	 * disables the box.
	 */
	var checkboxSel = "#" + tableId + " " + baseCheckboxSel;

	$(checkboxSel + ":checked:disabled, " + checkboxSel + ":enabled").parents(
			"tr").children("td.item").each(function() {
		var box = $(this).parents("tr").find(baseCheckboxSel);
		var isSelected = jQuery.inArray($(this).text(), selectedItems) > -1;

		box.each(function() {
			this.checked = isSelected;
			setFormElementEnabled($(this), !isSelected);
		});
	});
}

/**
 * Puts the items (content from a cell with class 'item') of the currently
 * selected table rows into a selection. The selection is stored in a HTML
 * "select" component.
 *
 * @param tableId
 *            A table ID
 * @return void
 */
function addItemsToSelection(tableId) {

	// getting the component storing the selected sub IDs
	var selItemsCmp = $('#' + selCmpId);

	// deselecting all options
	$('#' + selCmpId + ' option:selected').each(function() {
		setSelected($(this), false);
	});

	// for each sub ID corresponding to a checked box
	var selector = "#" + tableId + baseCheckboxSel + ":enabled:checked";
	var createdNb = 0;

	$(selector).parents("tr").children("td.item")
			.each(
					function() {
						var item = $(this).text();

						/* checking if the item is already in the selection */
						var canBeAdded = true;

						selItemsCmp.find("option").each(function() {
							if (item == $(this).text()) {
								canBeAdded = false;
							}
						});

						/* adding the item to the selection */
						if (canBeAdded) {
							setSelected($(
									'<option value="' + item + '">' + item
											+ '</option>')
									.appendTo(selItemsCmp), true);
							createdNb++;
						}
					});

	// deselecting all checkboxes
	$("#" + tableId + baseCheckboxSel + ":enabled").add('#' + mainCheckBoxId)
			.each(function() {
				this.checked = false;
			});

	// updating the components state
	updateRowsState(tableId);
	updateRowsStateForSelection(tableId);
	updateSelectionComponentState();

	if (createdNb == 0) {
		selectLastSelectionComponentOption();
	}

	if (isIE8()) {
		selItemsCmp.hide().show();
	}
}

/**
 *
 * Removes the items selected in the selection component.
 *
 * @param tableId
 *            A table ID
 * @return void
 */
function removeItemsFromSelection(tableId) {

	// new selection computation, step 1
	var selEls = $('#' + selCmpId + ' option:selected');
	var nextEls = selEls.nextAll().not(selEls).not(selEls.eq(0).prevAll());

	// removing the selected options
	selEls.remove();

	// new selection computation, step 2
	if (nextEls.length == 0) {

		nextEls = $('#' + selCmpId + ' option:last');
	}

	if (nextEls.length > 0) {
		nextEls.first().each(function() {
			setSelected($(this), true);
		});
	}

	// updating the components state
	updateRowsState(tableId);
	updateRowsStateForSelection(tableId);
	updateSelectionComponentState();
}

/**
 * Submits the form used by the display tag table
 *
 * @param formname
 *            The form name
 * @param fields
 *            The fields to submit
 * @return void
 */
function displaytagform(formname, fields) {

	var objfrm = document.forms[formname];

	for (j = fields.length - 1; j >= 0; j--) {

		var f = objfrm.elements[fields[j].f];
		if (f) {

			f.value = fields[j].v
		}
	}

	objfrm.submit();
}
